using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;
using HengTong.Model.Db;
using HengTong.Model.Db.SupplyChain.Material;
using HengTong.Model.Db.SupplyChain.Warehouse;
using HengTong.Model.Db.System;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using TiaoTaoHelper.Models;
using TiaoTaoHelper.Wtm.Models;
using WalkingTec.Mvvm.Core;
using WalkingTec.Mvvm.Mvc;
using TiaoTaoHelper.Wtm.Extension;
using TiaoTaoHelper.Wtm.Workflow;
using WalkingTec.Mvvm.Core.Extensions;

namespace HengTong.Controllers;

[AllRights]
[AuthorizeJwtWithCookie]
[Route("/api/common")]
[ApiController]
[NoLog]
public class SysCommonController(XenWorkflowService service) : BaseApiController
{
    /// <summary>
    /// 获取部门列表
    /// </summary>
    /// <param name="auth">是否进行权限过滤，默认为true。当为true时，只返回当前用户有权限访问的部门。仅对业务单据启用auth操作, 特定角色拥有全部部门的查看权限(人事、办公室)等</param>
    /// <param name="orgId">公司/机构ID</param>
    /// <param name="showCompany">是否显示公司, 默认为 false, 如果为true则移除顶级部门, 所有的公司作为第一层级, 然后然后公司下的部门, 需要注意的是所有的部门需要将 Tag设置为公司 ID，如果是公司则留空，前端根据TAG来判断和读取公司 ID</param>
    /// <returns>返回部门下拉列表项数组</returns>
    /// <response code="200">成功返回部门列表</response>
    [ActionDescription("获取部门")]
    [HttpGet("[action]")]
    public async Task<TreeSelectListItem[]> GetGroups([FromQuery] bool auth = true, [FromQuery] Guid? orgId = null,
        [FromQuery] bool showCompany = false)
    {
        var groups = await DC.Set<SysGroup>()
            .Where(e => !e.IsDisabled) // 添加禁用过滤
            .CheckWhere(orgId, x => x.Organizations.Any(e => e.OrgId == orgId))
            .Include(e => e.Organizations)
            .AsNoTracking()
            .OrderBy(e => e.Order)
            .ToListAsync();
        groups.ForEach(e => e.Organizations.ForEach(o => o.Group = null));
        List<SysGroup> data;
        if (showCompany)
        {
            var d = new List<TreeSelectListItem>();
            var orgList = await DC.Set<SysOrg>()
                .AsNoTracking()
                .OrderBy(x => x.Order ?? 99.99m)
                .ToArrayAsync();
            foreach (var orgItem in orgList)
            {
                var list = JsonSerializer.Deserialize<List<SysGroup>>(JsonSerializer.Serialize(groups));
                var groupList = list.Where(e => e.Organizations.Any(x => x.OrgId == orgItem.ID))
                    .OrderBy(e => e.Order)
                    .ToList();
                var groupTree = groupList.ToTreeSelectListItems<SysGroup, FrameworkGroup>(x => x.GroupName, x => x.ID,
                    tagSelector: x => orgItem.ID.ToString());
                var orgItemTree = new TreeSelectListItem
                {
                    Id = orgItem.ID.ToString(),
                    Text = orgItem.Name,
                    Value = orgItem.ID.ToString(),
                    Children = groupTree.FirstOrDefault()?.Children,
                    Tag = ""
                };
                d.Add(orgItemTree);
            }

            return d.ToArray();
        }

        if (auth && !Wtm.LoginUserInfo.Roles.Any(e => e.RoleCode == "001" || e.RoleCode == "201"))
        {
            var groupIds = Wtm.LoginUserInfo.Groups.Select(e => e.ID).ToArray();
            data = groups.ToTree<SysGroup, FrameworkGroup>(groupIds);
        }
        else
        {
            data = groups.ToTree<SysGroup, FrameworkGroup>();
        }

        if (orgId != null)
        {
            return data.ToTreeSelectListItems<SysGroup, FrameworkGroup>(x => x.GroupName,
                tagSelector: x => orgId.ToString());
        }
        else
        {
            return data.ToTreeSelectListItems<SysGroup, FrameworkGroup>(x => x.GroupName);
        }
    }


    
    /// <summary>
    /// 获取物料分组属性列表
    /// </summary>
    /// <returns></returns>
    [ActionDescription("获取物料分组")]
    [HttpGet("[action]")]
    public async Task<TreeSelectListItem[]> GetMaterialGroups()
    {
        var groups = await DC.Set<SysMaterialGroup>()
            .AsNoTracking()
            .ToListAsync();
        var data = groups.ToTreeSelectListItems(x => x.Name);
        return data;
    }
    
    
    /// <summary>
    /// 获取岗位列表
    /// </summary>
    /// <param name="groupId">部门ID，可选参数。如果提供则只返回该部门下的岗位</param>
    /// <returns>返回岗位下拉列表项数组</returns>
    /// <response code="200">成功返回岗位列表</response>
    [ActionDescription("获取岗位列表")]
    [HttpGet("[action]")]
    public async Task<JobPositionComboItem[]> GetJobPositions([FromQuery] Guid? groupId)
    {
        var jobPositions = await DC.Set<SysJobPosition>()
            .AsNoTracking()
            .OrderBy(x => x.Order ?? 99.99m)
            .ToListAsync();
        if (groupId != null)
        {
            jobPositions = jobPositions.Where(e => e.GroupId == groupId).ToList();
        }

        var data = jobPositions
            .Select(e => new JobPositionComboItem
            {
                Value = e.ID.ToString(),
                Text = e.Name,
                Salary = e.Salary
            })
            .ToArray();
        return data;
    }
    public class JobPositionComboItem : ComboSelectListItem
    {
        public decimal? Salary { get; set; }
    }

    /// <summary>
    /// 获取审批流时间线数据
    /// </summary>
    /// <param name="entityId">实体ID，用于查询相关的审批流历史记录</param>
    /// <returns>返回审批流历史记录列表，包含审批的各个节点和时间信息</returns>
    /// <response code="200">成功返回审批流时间线数据</response>
    [HttpGet("[action]")]
    public async Task<List<SysWorkflowHistory>> GetTimeLine([FromQuery] string entityId)
    {
        var data = await service.GetTimeLineAsync(entityId);
        return data;
    }

    /// <summary>
    /// 获取组织机构列表
    /// <param name="groupId">查询拥有该部门的组织机构, 如果为空则返回全部组织机构列表</param>
    /// </summary>
    /// <returns></returns>
    [HttpGet("[action]")]
    public async Task<List<ComboSelectListItem>> GetOrganizations([FromQuery] Guid? groupId)
    {
        if (groupId != null)
        {
            var group = await DC.Set<SysGroup>()
                .Where(e => !e.IsDisabled) // 添加禁用过滤
                .AsNoTracking()
                .Include(e => e.Organizations)
                .ThenInclude(e => e.Org)
                .Where(e => e.ID == groupId)
                .OrderBy(e => e.Order ?? 99.99m)
                .FirstOrDefaultAsync();
            var data = group.Organizations.OrderBy(e => e.Org.Order).Select(e => new ComboSelectListItem()
            {
                Value = e.Org.ID.ToString(),
                Text = e.Org.Name
            });
            return data.ToList();
        }

        var list = DC.Set<SysOrg>()
            .OrderBy(e => e.Order)
            .GetSelectListItems(Wtm, x => x.Name);
        return list;
    }

    /// <summary>
    /// 获取仓库列表
    /// </summary>
    /// <returns></returns>
    [HttpGet("[action]")]
    public async Task<List<SysWarehouse>> GetWarehouse()
    {
        if (Wtm.LoginUserInfo != null && Guid.TryParse(Wtm.LoginUserInfo.UserId, out var userId))
        {
            var orgIds = await DC.Set<SysUserJobPosition>()
                .AsNoTracking()
                .Where(e => e.UserId == userId)
                .SelectMany(e => e.JobPosition.Organizations)
                .Select(e => e.OrgId)
                .Distinct()
                .ToListAsync();
            var data = await DC.Set<SysWarehouse>()
                .AsNoTracking()
                .CheckContain(orgIds, x => x.OrgId)
                .ToListAsync();
            return data;
        }
        return [];
    }


    /// <summary>
    /// 获取公司-部门-岗位树形结构
    /// </summary>
    /// <param name="auth">是否进行权限过滤，默认为true。为true时只返回当前用户有权限访问的部门及岗位</param>
    /// <param name="orgId">公司/机构ID，可选参数。指定时只返回该公司下的部门和岗位</param>
    /// <param name="showCompany">是否显示公司节点，默认为false。为true时公司作为第一层级节点</param>
    /// <returns>返回公司-部门-岗位树形结构数组</returns>
    /// <response code="200">成功返回组织架构树形数据</response>
    [ActionDescription("获取公司-部门-岗位树")]
    [HttpGet("[action]")]
    public async Task<OrgTreeNode[]> GetOrgTree([FromQuery] bool auth = true, [FromQuery] Guid? orgId = null,
        [FromQuery] bool showCompany = false)
    {
        // 获取用户权限范围内的部门ID（如果需要权限过滤）
        var userGroupIds = auth && Wtm.LoginUserInfo.Roles.All(e => e.RoleCode != "001")
            ? Wtm.LoginUserInfo.Groups.Select(e => e.ID).ToArray()
            : null;

        // 一次性查询所有需要的数据
        var groupsQuery = DC.Set<SysGroup>()
            .Where(g => !g.IsDisabled) // 添加禁用过滤
            .Include(g => g.Organizations)
            .ThenInclude(o => o.Org)
            .CheckWhere(orgId, x => x.Organizations.Any(e => e.OrgId == orgId))
            .CheckWhere(userGroupIds != null, x => userGroupIds.Contains(x.ID))
            .AsNoTracking();

        var positionsQuery = DC.Set<SysJobPosition>()
            .CheckWhere(userGroupIds != null, x => x.GroupId.HasValue && userGroupIds.Contains(x.GroupId.Value))
            .AsNoTracking();

        // 并行执行查询
        var groups = await groupsQuery.OrderBy(e => e.Order ?? 99.99m).ToListAsync();
        var positions = await positionsQuery.OrderBy(x => x.Order ?? 99.99m).ThenBy(x => x.Name).ToListAsync();

        if (showCompany)
        {
            return BuildCompanyTree(groups, positions, orgId);
        }
        else
        {
            return BuildDepartmentTree(groups, positions);
        }
    }

    private OrgTreeNode[] BuildCompanyTree(List<SysGroup> groups, List<SysJobPosition> positions, Guid? orgId)
    {
        var orgs = groups
            .SelectMany(g => g.Organizations.Select(o => o.Org))
            .Where(o => !orgId.HasValue || o.ID == orgId)
            .DistinctBy(o => o.ID)
            .OrderBy(o => o.Order ?? 99.99m);

        return orgs.Select(org => new OrgTreeNode
        {
            Id = org.ID.ToString(),
            Name = org.Name,
            Type = "company",
            Children = BuildDepartmentNodes(
                groups.Where(g => g.Organizations.Any(o => o.OrgId == org.ID)),
                positions
            )
        }).ToArray();
    }

    private OrgTreeNode[] BuildDepartmentTree(List<SysGroup> groups, List<SysJobPosition> positions)
    {
        return BuildDepartmentNodes(groups, positions).ToArray();
    }

    private List<OrgTreeNode> BuildDepartmentNodes(IEnumerable<SysGroup> groups, List<SysJobPosition> positions)
    {
        return groups.Select(group => new OrgTreeNode
        {
            Id = group.ID.ToString(),
            Name = group.GroupName,
            Type = "department",
            Children = positions
                .Where(p => p.GroupId == group.ID)
                .Select(pos => new OrgTreeNode
                {
                    Id = pos.ID.ToString(),
                    Name = pos.Name,
                    Type = "position"
                }).ToList()
        }).ToList();
    }

    /// <summary>
    /// 获取岗位信息（第三方调用）
    /// </summary>
    /// <param name="groupId">部门ID，可选参数。如果提供则只返回该部门下的岗位</param>
    /// <param name="lastSyncTime">上次同步时间，可选。用于增量同步，只返回该时间之后创建或更新的岗位</param>
    /// <returns>返回岗位基本信息列表</returns>
    /// <response code="200">成功返回岗位信息</response>
    [ActionDescription("获取岗位信息三方调用")]
    [HttpGet("[action]")]
    public async Task<Result<List<JobPositionInfoView>>> GetJobPositionInfoForThirdParty(
        [FromQuery] Guid? groupId = null,
        [FromQuery] DateTime? lastSyncTime = null)
    {
        try
        {
            var query = DC.Set<SysJobPosition>()
                .Include(x => x.Group) // 包含部门信息
                .AsNoTracking()
                .CheckWhere(groupId, x => x.GroupId == groupId) // 条件过滤部门ID
                .CheckWhere(lastSyncTime, x => x.UpdateTime >= lastSyncTime.Value ||
                                               x.CreateTime >= lastSyncTime.Value); // 条件过滤更新时间

            var jobPositions = await query
                .OrderBy(x => x.Order ?? 99.99m) // 按排序字段排序
                .ThenBy(x => x.Name) // 二级排序按名称
                .ToListAsync();

            var result = jobPositions.Select(position => new JobPositionInfoView
            {
                Id = position.ID,
                Code = position.Code,
                Name = position.Name,
                IsManager = position.IsManager,
                GroupId = position.GroupId,
                GroupCode = position.Group?.GroupCode,
                GroupName = position.Group?.GroupName ?? "未分配部门",
                GroupIsDisabled = position.Group?.IsDisabled ?? false, // 添加部门禁用状态
                CreateTime = position.CreateTime,
                UpdateTime = position.UpdateTime
            }).ToList();

            return new Result<List<JobPositionInfoView>>
            {
                Data = result
            };
        }
        catch (Exception ex)
        {
            return new Result<List<JobPositionInfoView>>($"获取岗位信息失败：{ex.Message}");
        }
    }

    /// <summary>
    /// 获取部门信息（第三方调用）
    /// </summary>
    /// <param name="orgId">公司/机构ID，可选参数。如果提供则只返回该公司下的部门</param>
    /// <param name="parentId">父级部门ID，可选参数。如果提供则只返回该部门下的子部门</param>
    /// <param name="lastSyncTime">上次同步时间，可选。用于增量同步，只返回该时间之后创建或更新的岗位</param>
    /// <returns>返回部门基本信息列表，包含层级关系</returns>
    /// <response code="200">成功返回部门信息</response>
    [ActionDescription("获取部门信息三方调用")]
    [HttpGet("[action]")]
    public async Task<Result<List<GroupInfoView>>> GetGroupInfoForThirdParty(
        [FromQuery] Guid? orgId = null,
        [FromQuery] Guid? parentId = null,
        [FromQuery] DateTime? lastSyncTime = null)
    {
        try
        {
            var query = DC.Set<SysGroup>()
                .Include(x => x.Organizations)
                .ThenInclude(x => x.Org)
                .AsNoTracking()
                .CheckWhere(orgId, x => x.Organizations.Any(e => e.OrgId == orgId)) // 条件过滤公司ID
                .CheckWhere(parentId, x => x.ParentId == parentId) // 条件过滤父级部门ID
                .CheckWhere(lastSyncTime, x => x.UpdateTime >= lastSyncTime.Value ||
                                               x.CreateTime >= lastSyncTime.Value); // 条件过滤更新时间

            var groups = await query
                .OrderBy(x => x.Order ?? 99.99m) // 按排序字段排序
                .ThenBy(x => x.GroupName) // 二级排序按名称
                .ToListAsync();

            var result = groups.Select(group => new GroupInfoView
            {
                Id = group.ID,
                Code = group.GroupCode,
                Name = group.GroupName,
                FullName = group.FullName,
                Level = group.Level,
                ParentId = group.ParentId,
                IsVirtual = group.IsVirtual,
                IsDisabled = group.IsDisabled, // 添加禁用状态字段
                Order = group.Order,
                CreateTime = group.CreateTime,
                UpdateTime = group.UpdateTime,
                OrgIds = group.Organizations?.Select(o => o.OrgId).Where(id => id.HasValue).Select(id => id.Value)
                    .ToList() ?? new List<Guid>(),
                OrgNames = group.Organizations?.Where(o => o.Org != null).Select(o => o.Org.Name).ToList() ??
                           new List<string>()
            }).ToList();

            return new Result<List<GroupInfoView>>
            {
                Data = result
            };
        }
        catch (Exception ex)
        {
            return new Result<List<GroupInfoView>>($"获取部门信息失败：{ex.Message}");
        }
    }

    /// <summary>
    /// 获取组织机构信息（第三方调用）
    /// </summary>
    /// <param name="parentId">父级组织ID，可选参数。如果提供则只返回该组织下的子组织</param>
    /// <param name="lastSyncTime">上次同步时间，可选。用于增量同步，只返回该时间之后创建或更新的组织</param>
    /// <returns>返回组织机构基本信息列表，包含层级关系</returns>
    /// <response code="200">成功返回组织机构信息</response>
    [ActionDescription("获取组织机构信息三方调用")]
    [HttpGet("[action]")]
    public async Task<Result<List<OrgInfoView>>> GetOrgInfoForThirdParty(
        [FromQuery] Guid? parentId = null,
        [FromQuery] DateTime? lastSyncTime = null)
    {
        try
        {
            var query = DC.Set<SysOrg>()
                .AsNoTracking()
                .CheckWhere(parentId, x => x.ParentId == parentId) // 条件过滤父级组织ID
                .CheckWhere(lastSyncTime, x => x.UpdateTime >= lastSyncTime.Value ||
                                               x.CreateTime >= lastSyncTime.Value); // 条件过滤更新时间

            var orgs = await query
                .OrderBy(x => x.Order ?? 99.99m) // 按排序字段排序
                .ThenBy(x => x.Name) // 二级排序按名称
                .ToListAsync();

            var result = orgs.Select(org => new OrgInfoView
            {
                Id = org.ID,
                Code = org.Code,
                Name = org.Name,
                IsHrOrg = org.IsHrOrg,
                IsFinanceOrg = org.IsFinanceOrg,
                IsSupplyChainOrg = org.IsSupplyChainOrg,
                Order = org.Order,
                ParentId = org.ParentId,
                CreateTime = org.CreateTime,
                UpdateTime = org.UpdateTime
            }).ToList();

            return new Result<List<OrgInfoView>>
            {
                Data = result
            };
        }
        catch (Exception ex)
        {
            return new Result<List<OrgInfoView>>($"获取组织机构信息失败：{ex.Message}");
        }
    }

    /// <summary>
    /// 获取当前用户岗位所属的公司列表
    /// </summary>
    /// <param name="auth">是否进行权限过滤，默认为true。当为true时，只返回当前用户所属的公司；当为false时，返回所有公司</param>
    /// <returns>返回公司下拉列表项数组</returns>
    /// <response code="200">成功返回公司列表</response>
    [ActionDescription("获取当前用户岗位所属公司")]
    [HttpGet("[action]")]
    public async Task<ComboSelectListItem[]> GetUserCompanies([FromQuery] bool auth = true)
    {
        if (auth)
        {
            // 权限过滤：只返回当前用户所属的公司
            if (Wtm.LoginUserInfo == null)
            {
                return [];
            }

            if (!Guid.TryParse(Wtm.LoginUserInfo.UserId, out var currentUserId))
            {
                return [];
            }

            // 通过用户岗位关联表获取用户的岗位ID列表
            var userJobPositionIds = await DC.Set<SysUserJobPosition>()
                .Where(ujp => ujp.UserId == currentUserId)
                .Where(ujp => ujp.JobPositionId.HasValue)
                .Select(ujp => ujp.JobPositionId.Value)
                .ToListAsync();

            if (!userJobPositionIds.Any())
            {
                return [];
            }

            // 直接通过岗位的组织关联获取公司信息
            var companies = await DC.Set<SysJobPosition>()
                .Where(jp => userJobPositionIds.Contains(jp.ID))
                .Include(jp => jp.Organizations)
                .ThenInclude(o => o.Org)
                .AsNoTracking()
                .SelectMany(jp => jp.Organizations.Select(o => o.Org))
                .Where(org => org != null)
                .Distinct()
                .OrderBy(org => org.Order ?? 99.99m)
                .ThenBy(org => org.Name)
                .Select(org => new ComboSelectListItem
                {
                    Value = org.ID.ToString().ToLower(),
                    Text = org.Name
                })
                .ToArrayAsync();

            return companies;
        }
        else
        {
            // 不进行权限过滤：返回所有公司
            var companies = await DC.Set<SysOrg>()
                .AsNoTracking()
                .OrderBy(org => org.Order ?? 99.99m)
                .ThenBy(org => org.Name)
                .Select(org => new ComboSelectListItem
                {
                    Value = org.ID.ToString().ToLower(),
                    Text = org.Name
                })
                .ToArrayAsync();

            return companies;
        }
    }
    

    public class OrgTreeNode
    {
        public string Id { get; set; }
        public string Name { get; set; }
        public string Type { get; set; } // company/department/position
        public List<OrgTreeNode> Children { get; set; } = new();
    }

    /// <summary>
    /// 岗位信息视图（第三方调用）
    /// </summary>
    public class JobPositionInfoView
    {
        /// <summary>
        /// 岗位ID
        /// </summary>
        public Guid Id { get; set; }

        /// <summary>
        /// 岗位编号
        /// </summary>
        public string Code { get; set; }

        /// <summary>
        /// 岗位名称
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// 是否为主管
        /// </summary>
        public bool IsManager { get; set; }

        /// <summary>
        /// 所属部门ID
        /// </summary>
        public Guid? GroupId { get; set; }

        /// <summary>
        /// 所属部门编号
        /// </summary>
        public string GroupCode { get; set; }

        /// <summary>
        /// 所属部门名称
        /// </summary>
        public string GroupName { get; set; }

        /// <summary>
        /// 所属部门是否禁用
        /// </summary>
        public bool GroupIsDisabled { get; set; }

        public DateTime? CreateTime { get; set; }
        public DateTime? UpdateTime { get; set; }
    }

    /// <summary>
    /// 部门信息视图（第三方调用）
    /// </summary>
    public class GroupInfoView
    {
        /// <summary>
        /// 部门ID
        /// </summary>
        public Guid Id { get; set; }

        /// <summary>
        /// 部门编号
        /// </summary>
        public string Code { get; set; }

        /// <summary>
        /// 部门名称
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// 部门全称
        /// </summary>
        public string FullName { get; set; }

        /// <summary>
        /// 层级
        /// </summary>
        public uint Level { get; set; }

        /// <summary>
        /// 父级部门ID
        /// </summary>
        public Guid? ParentId { get; set; }

        /// <summary>
        /// 是否虚拟部门
        /// </summary>
        public bool IsVirtual { get; set; }

        /// <summary>
        /// 是否禁用
        /// </summary>
        public bool IsDisabled { get; set; }

        /// <summary>
        /// 排序
        /// </summary>
        public decimal? Order { get; set; }

        /// <summary>
        /// 关联的组织ID列表
        /// </summary>
        public List<Guid> OrgIds { get; set; }

        /// <summary>
        /// 关联的组织名称列表
        /// </summary>
        public List<string> OrgNames { get; set; }

        public DateTime? CreateTime { get; set; }
        public DateTime? UpdateTime { get; set; }
    }

    /// <summary>
    /// 组织机构信息视图（第三方调用）
    /// </summary>
    public class OrgInfoView
    {
        /// <summary>
        /// 组织机构ID
        /// </summary>
        public Guid Id { get; set; }

        /// <summary>
        /// 组织编码
        /// </summary>
        public string Code { get; set; }

        /// <summary>
        /// 组织名称
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// 是否人事组织
        /// </summary>
        public bool IsHrOrg { get; set; }

        /// <summary>
        /// 是否财务组织
        /// </summary>
        public bool IsFinanceOrg { get; set; }

        /// <summary>
        /// 是否供应链组织
        /// </summary>
        public bool IsSupplyChainOrg { get; set; }

        /// <summary>
        /// 排序
        /// </summary>
        public decimal? Order { get; set; }

        /// <summary>
        /// 父级组织ID
        /// </summary>
        public Guid? ParentId { get; set; }

        /// <summary>
        /// 创建时间
        /// </summary>
        public DateTime? CreateTime { get; set; }

        /// <summary>
        /// 更新时间
        /// </summary>
        public DateTime? UpdateTime { get; set; }
    }
}